package java8.optional;

import org.junit.Test;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

public class OptionalTest {
    //创建
    @Test
    public void create() {
        //为非null的值创建一个Optional，如果值为null,则会抛出NullPointerException
        Optional<Integer> optional = Optional.of(13);
        System.out.println(optional);
        //为指定的值创建一个Optional，如果指定的值为null，则返回一个空的Optional。
        Optional<String> optional2 = Optional.ofNullable(null);
        System.out.println(optional2);
        optional2 = Optional.ofNullable("aaa");
        System.out.println(optional2);
    }

    //如果值存在返回true，否则返回false。
    @Test
    public void ofNullable() {
        Optional<String> optional2 = Optional.ofNullable(null);
        System.out.println(optional2);
        System.out.println(optional2.isPresent());

        optional2 = Optional.ofNullable("aaa");
        System.out.println(optional2);
        //如果值存在返回true，否则返回false。
        System.out.println(optional2.isPresent());
    }

    //如果Optional有值则将其返回，否则抛出NoSuchElementException。
    @Test
    public void get() {
        Optional optional2 = Optional.ofNullable("aaa");
        System.out.println(optional2);
        System.out.println(optional2.isPresent());
        System.out.println(optional2.get());
    }

    //如果Optional实例有值则为其调用consumer，否则不做处理 。隐士地其中进行了null判断
    @Test
    public void ifPresent() {
        String str1 = "hello";
        String str2 = null;
        Optional<String> optional1 = Optional.ofNullable(str1);
        Optional<String> optional2 = Optional.ofNullable(str2);
        optional1.ifPresent(str -> System.out.println(str.length()));
        optional2.ifPresent(str -> System.out.println(str.length()));
    }


    //如果有值则将其返回，否则返回指定的其它值。
    @Test
    public void orElse() {
        String str1 = "hello";
        String str2 = null;
        Optional<String> optional1 = Optional.ofNullable(str1);
        Optional<String> optional2 = Optional.ofNullable(str2);
        System.out.println(optional1.orElse("默认字符串"));
        System.out.println(optional2.orElse("默认字符串"));
    }

    //orElseGet与orElse方法类似，区别在于得到的默认值。orElse方法将传入的一个值作为默认值，orElseGet方法可以接受Supplier接口的实现用来生成默认值
    @Test
    public void orElseGet() {
        Integer i = 20;
        Optional<Integer> op = Optional.ofNullable(i);
        System.out.println(op.orElseGet(() -> 0));
        System.out.println(Optional.ofNullable(null).orElseGet(() -> 0));
    }

    @Test
    public void orElseThrow() {
        // 自己指定异常
        System.out.println((Optional.ofNullable("a").orElseThrow(() -> new IndexOutOfBoundsException())));
        System.out.println((Optional.ofNullable(null).orElseThrow(() -> new IndexOutOfBoundsException())));
    }

    //map处理有值的情况，如果有值，则对其执行调用map参数中的函数得到返回值，否则返回空Optional。
    @Test
    public void map() {
        List<String> list = new ArrayList<String>() {
            {
                add("aaa");
                add("bbb");
                add(null);
            }
        };

        list.stream().forEach(temp -> {
            Optional<String> opt = Optional.ofNullable(temp);
            System.out.println(opt.map(n -> {
                return n.toUpperCase();
            }).orElse("Nothing"));
        });

        // 简写为如下形式
        list.stream().forEach(temp -> {
            System.out.println(Optional.ofNullable(temp).map(n -> n.toUpperCase()).orElse("Nothing"));
        });

    }

    //如果有值，为其执行mapping函数返回Optional类型返回值，否则返回空Optional。flatMap与map（Funtion）方法类似
    //区别在于flatMap中的mapper返回值必须是Optional。调用结束时，flatMap不会对结果用Optional封装。
    @Test
    public void flatMap() {
        Optional<String> opt1 = Optional.ofNullable("aaa");
        Optional<String> opt2 = Optional.ofNullable(null);
        System.out.println(opt1.flatMap(n -> {
            return Optional.ofNullable(n.toUpperCase());
        }).orElse("还会没有吗"));

        System.out.println(opt2.flatMap(n -> {
            return Optional.ofNullable(n.toUpperCase());
        }).orElse("还会没有吗"));
    }


    //如果有值并且满足断言条件返回包含该值的Optional，否则返回空Optional。
    @Test
    public void filter() {
        Optional<String> opt1 = Optional.ofNullable("aabbbbaa");
        Optional<String> opt2 = Optional.ofNullable(null);

        System.out.println(opt1.filter(value->value.length()>6));
        System.out.println(opt2.filter(value->value.length()>6));
    }
}
